/**
 * Title: AsyncHttpClient.java
 * Description:
 * Copyright: Copyright (c) 2008
 * Company:深圳彩讯科技有限公司
 * Author 罗旭东 (hi@luoxudong.com)
 * Date 2013-8-15 上午9:17:16
 * Version 1.0 
 */
package com.luoxudong.phonenumber.service.net.http.asynchttp;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;

import com.luoxudong.phonenumber.service.net.http.httpclient.Header;
import com.luoxudong.phonenumber.service.net.http.httpclient.HeaderElement;
import com.luoxudong.phonenumber.service.net.http.httpclient.HttpEntity;
import com.luoxudong.phonenumber.service.net.http.httpclient.HttpRequest;
import com.luoxudong.phonenumber.service.net.http.httpclient.HttpRequestInterceptor;
import com.luoxudong.phonenumber.service.net.http.httpclient.HttpResponse;
import com.luoxudong.phonenumber.service.net.http.httpclient.HttpResponseInterceptor;
import com.luoxudong.phonenumber.service.net.http.httpclient.HttpVersion;
import com.luoxudong.phonenumber.service.net.http.httpclient.conn.scheme.PlainSocketFactory;
import com.luoxudong.phonenumber.service.net.http.httpclient.conn.scheme.Scheme;
import com.luoxudong.phonenumber.service.net.http.httpclient.conn.scheme.SchemeRegistry;
import com.luoxudong.phonenumber.service.net.http.httpclient.conn.ssl.SSLSocketFactory;
import com.luoxudong.phonenumber.service.net.http.httpclient.entity.HttpEntityWrapper;
import com.luoxudong.phonenumber.service.net.http.httpclient.impl.client.DefaultHttpClient;
import com.luoxudong.phonenumber.service.net.http.httpclient.impl.conn.PoolingClientConnectionManager;
import com.luoxudong.phonenumber.service.net.http.httpclient.params.BasicHttpParams;
import com.luoxudong.phonenumber.service.net.http.httpclient.params.HttpConnectionParams;
import com.luoxudong.phonenumber.service.net.http.httpclient.params.HttpProtocolParams;
import com.luoxudong.phonenumber.service.net.http.httpclient.protocol.HttpContext;
import com.luoxudong.phonenumber.service.pool.manager.ThreadTaskObject;
import com.luoxudong.phonenumber.service.utils.EvtLog;

/** 
 * ClassName: AsyncHttpClient
 * Description:创建httpclient单例对象
 * Create by 罗旭东
 * Date 2013-8-15 上午9:17:16
 */
public class AsyncHttpClient {
	private static final String TAG = "AsyncHttpClient";
	
	private static DefaultHttpClient httpClient = null;
	
	/**
	 * 
	 * @description:创建单例httpClient对象
	 * @return
	 * @return HttpClient
	 * @throws
	 */
	public static synchronized DefaultHttpClient getAsyncHttpClient()
	{
		if (httpClient == null) {
			EvtLog.i(TAG, "正在创建HttpClient对象");
			BasicHttpParams httpParams = new BasicHttpParams();

			HttpConnectionParams.setSoTimeout(httpParams, AsyncHttpConst.DEFAULT_SOCKET_TIMEOUT);
			HttpConnectionParams.setConnectionTimeout(httpParams, AsyncHttpConst.DEFAULT_SOCKET_TIMEOUT);
			HttpConnectionParams.setTcpNoDelay(httpParams, true);
			HttpConnectionParams.setSocketBufferSize(httpParams, AsyncHttpConst.DEFAULT_SOCKET_BUFFER_SIZE);

			HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
			HttpProtocolParams.setUserAgent(httpParams, String.format(AsyncHttpConst.USER_AGENT, AsyncHttpConst.USER_AGENT_VERSION));
			HttpProtocolParams.setContentCharset(httpParams, AsyncHttpConst.HTTP_ENCODING);

			/*SSLContext sslContext = null;

			try {
				sslContext = SSLContext.getInstance("SSL");
				sslContext.init(null, null, null);
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (KeyManagementException e) {
				e.printStackTrace();
			}

			SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext, SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
			*/
			SchemeRegistry schemeRegistry = new SchemeRegistry();
			schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
			schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
			PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);// 线程安全连接池

			cm.setDefaultMaxPerRoute(AsyncHttpConst.MAX_PER_ROUTE);
			cm.setMaxTotal(AsyncHttpConst.MAX_CONNECTIONS);

			httpClient = new DefaultHttpClient(cm, httpParams);

			// HTTP协议请求拦截器
			httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
				@Override
				public void process(HttpRequest request, HttpContext context) {
					if (!request.containsHeader(AsyncHttpConst.HEADER_ACCEPT_ENCODING)) {
						request.addHeader(AsyncHttpConst.HEADER_ACCEPT_ENCODING, AsyncHttpConst.ENCODING_GZIP);
					}
				}
			});

			//HTTP协议应答拦截器
			httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
				@Override
				public void process(HttpResponse response, HttpContext context) {
					final HttpEntity entity = response.getEntity();
					
					if (entity == null) {
						return;
					}
					
					EvtLog.i(TAG, "HTTP请求返回码[" + response.getStatusLine().getStatusCode() + "]");
					
					final Header encoding = entity.getContentEncoding();
					if (encoding != null) {
						for (HeaderElement element : encoding.getElements()) {
							if (element.getName().equalsIgnoreCase(AsyncHttpConst.ENCODING_GZIP)) {
								response.setEntity(new InflatingEntity(response
										.getEntity()));
								break;
							}
						}
					}
				}
			});

			httpClient.setHttpRequestRetryHandler(new RetryHandler(
					AsyncHttpConst.DEFAULT_MAX_RETRIES));
		}
		
		return httpClient;
	}
	
	/**
	 * 
	 * @description:关闭httpClient连接
	 * @return void
	 * @throws
	 */
	public static synchronized void closeAsyHttpClient()
	{
		if (httpClient != null)
		{
			EvtLog.i(TAG, "正在销毁HttpClient对象");
			new ThreadTaskObject(){
				public void run() {
					synchronized (httpClient) {
						httpClient.getConnectionManager().shutdown();
						httpClient = null;
					}
				};
			}.start();
		}
	}
	
	/**
	 * 
	 * @description:设置ssl传输
	 * @param sslSocketFactory
	 * @return void
	 * @throws
	 */
	public static void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) {
        httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, sslSocketFactory));
    }
	
	private static class InflatingEntity extends HttpEntityWrapper {
        public InflatingEntity(HttpEntity wrapped) {
            super(wrapped);
        }

        @Override
        public InputStream getContent() throws IOException {
            return new GZIPInputStream(wrappedEntity.getContent());
        }

        @Override
        public long getContentLength() {
            return -1;
        }
    }
}
